Матч 255, К-ый элемент (KthElement)

Дивизион 2, Уровень 3

 

Обозначим через F(n) функцию, которая вычисляет количество единиц в бинарном представлении числа n. Например, F(279) = 5, так как 279 = (100010111)2. Последовательность Х строится следующим образом: X0 = 0, Xi = A * F(Xi-1) + B. По заданным A, B, K найти K – ый элемент последовательности Х.

 

Класс: KthElement

Метод: int find(int A, int B, int K)

Ограничения: 0 £ A, B £ 106, 1 £ K £ 109.

 

Вход. Три числа A, B, K.

 

Выход. Значение Xk.

 

Пример входа

A

B

K

0

12

5

1

7

15

15

21

500000001

 

Пример выхода

12

9

51

 

 

РЕШЕНИЕ

математика

 

F(Xi) принимают конечное множество значений. Поэтому начиная с некоторого индекса pos, значения F(Xi) начнут образовывать повторяющийся цикл. Предположим, что индекс len минимальный, для которого Xpos = Xlen. Таким образом, длина цикла (повторяющейся части) равна lenpos. Все значения F(Xi), где i < len, будем хранить в векторе seq. То есть seq[i] = F(Xi) для i < len. Если искомый номер последовательности k < len, то достаточно вывести значение seq[k]. Иначе ищем минимальный индекс j последовательности X, для которого Xj = Xk. Он равен j = pos + (kpos) % (lenpos). Выводим seq[j] = Xj.

 

ПРИМЕР

 

Рассмотрим третий тест. Последовательность Xi имеет вид: 0, 21, 66, 51, 81, 66, 51, 81, 66, ... . Циклическая часть последовательности состоит из трех чисел и имеет вид 66, 51, 81. Для этой последовательности pos = 2 (нумерация индексов последовательности и вектора начинается с нуля), len = 5 (X2 = X5). Вычисляем минимальный индекс j последовательности X, для которого Xj = Xk: j = pos + (kpos) % (lenpos) = 2 + (500000001 – 2) % (5 – 2) = 2 + 1 = 3. Таким образом X500000001 = X3 = 51.

Функция int f(int x) вычисляет F(x).

 

ПРОГРАММА

 

#include <cstdio>

#include <algorithm>

#include <vector>

using namespace std;

 

class KthElement

{

public:

  int f(int x)

  {

    int res = 0;

    while(x > 0)

    {

      x = x & (x - 1);

      res++;

    }

    return res;

  }

 

  int find(int a, int b, int k)

  {

    vector<int> seq;

    int x = 0, pos, len;

    while(std::find(seq.begin(),seq.end(),x) == seq.end()) 

    {

       seq.push_back(x);

       x = a * f(x) + b;

    }

    pos = (int)(std::find(seq.begin(),seq.end(),x) - seq.begin());

    len = seq.size();

    if (k < len) return seq[k];

    return seq[pos + (k - pos) % (len - pos)];

  }

};